package cn.clx.ymcc.service.impl;


import cn.clx.ymcc.constant.RegisterConstant;
import cn.clx.ymcc.constants.BaseConstant;
import cn.clx.ymcc.constants.YmccExceptionError;
import cn.clx.ymcc.domain.MessageOver;
import cn.clx.ymcc.domain.MessageSms;
import cn.clx.ymcc.domain.User;
import cn.clx.ymcc.dto.RedisDto;
import cn.clx.ymcc.dto.RegisterDto;
import cn.clx.ymcc.feign.UserFeign;
import cn.clx.ymcc.service.IMessageOverService;
import cn.clx.ymcc.service.IMessageSmsService;
import cn.clx.ymcc.service.IVerifyCodeService;
import cn.clx.ymcc.util.AssertUtil;
import cn.clx.ymcc.util.StrUtils;
import cn.clx.ymcc.util.VerifyCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private UserFeign userFeign;

    @Autowired
    private RegisterConstant registerConstant;

    @Autowired
    private IMessageSmsService messageSmsService;

    @Autowired
    private IMessageOverService messageOverService;


    /**
     * 图形验证码实现
     * @param key
     * @return
     */
    @Override
    public String verificationCode(String key) {

        //随机生成一个四位数 作为验证码
        String code = StrUtils.getComplexRandomString(4);
        //存放在redis中 设置过期时间
        redisTemplate.opsForValue().set(key,code,registerConstant.getTimeout(), TimeUnit.SECONDS);

        //根据code生成图片并把图片转换成base64的字符串
        String verifyCode = VerifyCodeUtils.verifyCode(100,38,code);


        return verifyCode;
    }

    @Override
    public void sendSmsCode(RegisterDto dto) {
        String regChannel = dto.getRegChannel();
        String phone = dto.getMobile();
        if(regChannel.equals("register")){//用户短信注册
            userRegister(dto);
            String phoneCodekey = String.format(BaseConstant.RegisterConstants.REGISTER_SMS_PREFIX, phone);//register:phone
            verifyCode(phoneCodekey);
        }else if(regChannel.equals("binder")){
            //微信短信验证
            AssertUtil.isNotNull(phone,YmccExceptionError.NOT_EMP_NAME.getMessage());
            String phoneCodekey = String.format(BaseConstant.RegisterConstants.WECHAT_SMS_PREFIX, phone); //wechat:phone
            verifyCode(phoneCodekey);
        }

    }

    /**
     * 短信验证码通用
     * @param phoneCodekey
     */
    public void verifyCode(String phoneCodekey){

        RedisDto phonecode = (RedisDto) redisTemplate.opsForValue().get(phoneCodekey);
        String code=null;
        if(phonecode!=null){
            //现在的时间减去之前存储进去的时间，进行判断，过了60s没有
            Long data = phonecode.getData();
            code = phonecode.getCode();
            boolean canSend = System.currentTimeMillis() - data < 60 * 1000;
            AssertUtil.isTrue(!canSend,YmccExceptionError.EXCEPTION_REGISTER_TIME_ERROR.getMessage());

        }else {
            code = StrUtils.getRandomString(registerConstant.getSize());
        }
        RedisDto redisDto = new RedisDto();
        redisDto.setCode(code);
        redisDto.setData(System.currentTimeMillis());
        redisTemplate.opsForValue().set(phoneCodekey,redisDto,registerConstant.getTimeout(),TimeUnit.SECONDS);
        String format = String.format(registerConstant.getSmsmessage(),code);
        log.info(format);
        saveMessageSms(format,phoneCodekey);

    }

    /**
     * 保存messageSms 表
     * @param format
     */
    private void saveMessageSms(String format,String phoneCodekey) {
        String phone = phoneCodekey.split(":")[1];
        MessageSms messageSms = new MessageSms();
        messageSms.setContent(format);
        messageSms.setSendTime(new Date());
        messageSms.setTitle(registerConstant.getTitle());
        messageSms.setPhone(phone);
        // 获取请求体 request
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        messageSms.setIp(request.getRemoteAddr());//获取IP地址
        messageSmsService.insert(messageSms);
    }

    /**
     * 用户手机验证码注册
     * @param dto 参数
     */
    public void userRegister(RegisterDto dto) {
        String imageCodeKey = dto.getImageCodeKey();//UUID
        String imageCode = dto.getImageCode();
        String phone = dto.getMobile();

        //通过imageCodeKey拿value值
        Object imagetemp = redisTemplate.opsForValue().get(imageCodeKey);
        //使用断言来判断 验证码是否为空
        AssertUtil.isNotNull(imagetemp,YmccExceptionError.EXCEPTION_REGISTER_TIME_OUT_ERROR.getMessage());
        //验证码是否相等
        AssertUtil.isEqualsIgnoreCase(imagetemp.toString(),imageCode,YmccExceptionError.EXCEPTION_REGISTER_COMPARISON_ERROR.getMessage());

        //校验手机号是否被拉黑
        MessageOver over = messageOverService.loadByPhone(phone);
        AssertUtil.isNull(over,YmccExceptionError.USER_INFO_ISBLACK.getMessage());

        User user = userFeign.getByPhone(phone);
        AssertUtil.isNull(user,YmccExceptionError.EXCEPTION_REGISTER_REPEAT_ERROR.getMessage());


    }


}
